package utils

import (
	"gitee.com/showurl/push-rtmp/config"
	"gitee.com/showurl/push-rtmp/db"
	httpUtils "gitee.com/showurl/push-rtmp/utils/http"
	"github.com/go-resty/resty/v2"
	"log"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

var lastCmdExecTime = time.Now()

type RespGetBarrage struct {
	Code int `json:"code"`
	Data struct {
		Admin []struct {
			Text         string        `json:"text"`
			DmType       int           `json:"dm_type"`
			Uid          int           `json:"uid"`
			Nickname     string        `json:"nickname"`
			UnameColor   string        `json:"uname_color"`
			Timeline     string        `json:"timeline"`
			Isadmin      int           `json:"isadmin"`
			Vip          int           `json:"vip"`
			Svip         int           `json:"svip"`
			Medal        []interface{} `json:"medal"`
			Title        []string      `json:"title"`
			UserLevel    []interface{} `json:"user_level"`
			Rank         int           `json:"rank"`
			Teamid       int           `json:"teamid"`
			Rnd          string        `json:"rnd"`
			UserTitle    string        `json:"user_title"`
			GuardLevel   int           `json:"guard_level"`
			Bubble       int           `json:"bubble"`
			BubbleColor  string        `json:"bubble_color"`
			Lpl          int           `json:"lpl"`
			YeahSpaceUrl string        `json:"yeah_space_url"`
			JumpToUrl    string        `json:"jump_to_url"`
			CheckInfo    struct {
				Ts int    `json:"ts"`
				Ct string `json:"ct"`
			} `json:"check_info"`
			VoiceDmInfo struct {
				VoiceUrl     string `json:"voice_url"`
				FileFormat   string `json:"file_format"`
				Text         string `json:"text"`
				FileDuration int    `json:"file_duration"`
				FileId       string `json:"file_id"`
			} `json:"voice_dm_info"`
			Emoticon struct {
				Id             int    `json:"id"`
				EmoticonUnique string `json:"emoticon_unique"`
				Text           string `json:"text"`
				Perm           int    `json:"perm"`
				Url            string `json:"url"`
				InPlayerArea   int    `json:"in_player_area"`
				BulgeDisplay   int    `json:"bulge_display"`
				IsDynamic      int    `json:"is_dynamic"`
				Height         int    `json:"height"`
				Width          int    `json:"width"`
			} `json:"emoticon"`
		} `json:"admin"`
		Room []struct {
			Text         string        `json:"text"`
			DmType       int           `json:"dm_type"`
			Uid          int           `json:"uid"`
			Nickname     string        `json:"nickname"`
			UnameColor   string        `json:"uname_color"`
			Timeline     string        `json:"timeline"`
			Isadmin      int           `json:"isadmin"`
			Vip          int           `json:"vip"`
			Svip         int           `json:"svip"`
			Medal        []interface{} `json:"medal"`
			Title        []string      `json:"title"`
			UserLevel    []interface{} `json:"user_level"`
			Rank         int           `json:"rank"`
			Teamid       int           `json:"teamid"`
			Rnd          string        `json:"rnd"`
			UserTitle    string        `json:"user_title"`
			GuardLevel   int           `json:"guard_level"`
			Bubble       int           `json:"bubble"`
			BubbleColor  string        `json:"bubble_color"`
			Lpl          int           `json:"lpl"`
			YeahSpaceUrl string        `json:"yeah_space_url"`
			JumpToUrl    string        `json:"jump_to_url"`
			CheckInfo    struct {
				Ts int    `json:"ts"`
				Ct string `json:"ct"`
			} `json:"check_info"`
			VoiceDmInfo struct {
				VoiceUrl     string `json:"voice_url"`
				FileFormat   string `json:"file_format"`
				Text         string `json:"text"`
				FileDuration int    `json:"file_duration"`
				FileId       string `json:"file_id"`
			} `json:"voice_dm_info"`
			Emoticon struct {
				Id             int    `json:"id"`
				EmoticonUnique string `json:"emoticon_unique"`
				Text           string `json:"text"`
				Perm           int    `json:"perm"`
				Url            string `json:"url"`
				InPlayerArea   int    `json:"in_player_area"`
				BulgeDisplay   int    `json:"bulge_display"`
				IsDynamic      int    `json:"is_dynamic"`
				Height         int    `json:"height"`
				Width          int    `json:"width"`
			} `json:"emoticon"`
		} `json:"room"`
	} `json:"data"`
	Message string `json:"message"`
	Msg     string `json:"msg"`
}

func httpGetBarrage() *RespGetBarrage {
	resp := &RespGetBarrage{}
	url := "http://api.live.bilibili.com/ajax/msg?roomid=" + config.Config.Bilibili.Roomid
	httpUtils.ParseResponseJsonBody(func(r *resty.Request) (*resty.Response, error) {
		return r.Get(url)
	}, resp)
	return resp
}

func GetBarrage() {
	ticker := time.NewTicker(time.Second * time.Duration(config.Config.Bilibili.BarrageInterval))
	for {
		t := <-ticker.C
		barrage := httpGetBarrage()
		if barrage == nil {
			DingTalkSendMsg("获取弹幕失败", t.String())
			continue
		}
		if barrage.Code != 0 {
			DingTalkSendMsg("获取弹幕失败",
				"barrage.Code != 0",
				"code = "+strconv.Itoa(barrage.Code),
				"msg:"+barrage.Msg,
				"message:"+barrage.Message,
			)
			continue
		}
		for _, barrage := range barrage.Data.Room {
			for _, adminUid := range config.Config.Bilibili.AdminUids {
				if strings.HasPrefix(barrage.Text, config.Config.Bilibili.CmdPrefix) {
					timeline, err := time.ParseInLocation("2006-01-02 15:04:05", barrage.Timeline, time.Local)
					if err != nil {
						continue
					}
					if timeline.Sub(lastCmdExecTime).Seconds() > 0 {
						log.Println("lastCmdExecTime:", lastCmdExecTime.String())
						log.Println("timeline:", barrage.Timeline)
						// 指令有效
						// 执行指令
						// 看看是不是已经执行了
						if strconv.Itoa(barrage.Uid) == adminUid {
							// 可以控制
							execCmd(strings.TrimPrefix(barrage.Text, config.Config.Bilibili.CmdPrefix))
							lastCmdExecTime = timeline
						}
					}
				}
			}
		}
	}
}

func execCmd(command string) {
	kvs := strings.Split(command, "=")
	var k string
	var v string
	if len(kvs) == 2 {
		k, v = kvs[0], kvs[1]
	} else {
		return
	}
	switch k {
	case "jump":
		Jump(v, db.DB)
	case "show":
		switch v {
		case "filename":
			config.Config.PushCmdSetting = "show-text"
			err := Command(exec.Command("killall", "-9", "ffmpeg"))
			if err != nil {
				DingTalkSendMsg("killall失败", err.Error())
				return
			}
		case "none":
			config.Config.PushCmdSetting = ""
			err := Command(exec.Command("killall", "-9", "ffmpeg"))
			if err != nil {
				DingTalkSendMsg("killall失败", err.Error())
				return
			}
		}
	}
}
